package com.zz.bid.web.controller;

import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import com.github.pagehelper.PageInfo;
import com.zz.bid.annotation.RequiredAccess;
import com.zz.bid.exception.LoginTimeoutException;
import com.zz.bid.pojo.entity.BidFlowEnum;
import com.zz.bid.pojo.query.BidQuery;
import com.zz.bid.pojo.to.BidDesc;
import com.zz.bid.pojo.to.BidFlowDetails;
import com.zz.bid.pojo.to.ResponseWrapper;
import com.zz.bid.pojo.to.UserTO;
import com.zz.bid.service.BidFlowService;
import com.zz.bid.service.BidService;
import com.zz.bid.service.UserService;
import com.zz.bid.util.BidStatusEnum;
import com.zz.bid.web.controller.base.BaseController;

import lombok.extern.slf4j.Slf4j;

/**
 * @author chenkehan created at 2020/4/4 12:50 下午
 */
@RestController
@Slf4j
public class BidController extends BaseController {

    @Autowired
    private BidService bidService;

    @Autowired
    private UserService userService;

    @Autowired
    private BidFlowService bidFlowService;

    @PostMapping("/createBid")
    @RequiredAccess(101)
    public ResponseWrapper create(@RequestBody BidDesc bidDesc) {
        try {
            bidDesc.setCreatedBy(getUserTO().getUserId());
            bidDesc.setCreatedDate(LocalDateTime.now());
            bidService.create(bidDesc, getUserTO().getAccountName());
            // 将相应的流程也一并添加
            bidFlowService.addFlows(bidDesc.getId(), getUserTO().getAccountName());
            return ResponseWrapper.builder().status(HttpStatus.OK.value()).path(request.getServletPath()).data(true)
                .build();
        } catch (Exception e) {
            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            return ResponseWrapper.builder().status(HttpStatus.INTERNAL_SERVER_ERROR.value()).data(false)
                .path(request.getServletPath()).message(e.getMessage()).build();
        }
    }

    @PostMapping("/updateBid")
    @RequiredAccess(109)
    public ResponseWrapper update(@RequestBody BidDesc bidDesc) {
        try {
            bidService.update(bidDesc);
            return ResponseWrapper.builder().path(request.getServletPath()).data(true).status(HttpStatus.OK.value())
                .build();
        } catch (Exception e) {
            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            return ResponseWrapper.builder().status(HttpStatus.INTERNAL_SERVER_ERROR.value()).message(e.getMessage())
                .path(request.getContextPath()).data(false).build();
        }
    }

    @GetMapping("/updateStatus")
    @RequiredAccess(109)
    public ResponseWrapper updateStatus(@RequestParam("bidId") Integer bidId,
        @RequestParam("status") BidStatusEnum status) {
        try {
            UserTO userTO = getUserTO();
            bidService.updateStatus(bidId, userTO.getAccountName(), status);
            return ResponseWrapper.builder().path(request.getServletPath()).data(true).status(HttpStatus.OK.value())
                .build();
        } catch (Exception e) {
            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            return ResponseWrapper.builder().status(HttpStatus.INTERNAL_SERVER_ERROR.value()).message(e.getMessage())
                .path(request.getContextPath()).data(false).build();
        }
    }

    @PostMapping("/bidList")
    @RequiredAccess(107)
    public ResponseWrapper bidList(@RequestBody BidQuery bidQuery) {
        try {
            PageInfo<BidDesc> page = bidService.bidList(bidQuery);
            return ResponseWrapper.builder().path(request.getServletPath()).data(page).status(HttpStatus.OK.value())
                .build();
        } catch (Exception e) {
            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            return ResponseWrapper.builder().status(HttpStatus.INTERNAL_SERVER_ERROR.value()).message(e.getMessage())
                .path(request.getContextPath()).build();
        }
    }

    @GetMapping("bidExport")
    public void export() {
        // excel文件名
        String fileName = "招投标信息表" + System.currentTimeMillis() + ".xls";
        BidQuery bidQuery = new BidQuery();
        HSSFWorkbook wb = bidService.export(bidQuery);
        // 响应到客户端
        try {
            this.setResponseHeader(response, fileName);
            OutputStream os = response.getOutputStream();
            wb.write(os);
            os.flush();
            os.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @GetMapping("/bidDetails")
    @RequiredAccess(107)
    public ResponseWrapper bidDetails(int bidId) {
        try {
            BidDesc bidDesc = bidService.bidDetails(bidId);
            return ResponseWrapper.builder().path(request.getServletPath()).data(bidDesc).status(HttpStatus.OK.value())
                .build();
        } catch (Exception e) {
            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            return ResponseWrapper.builder().status(HttpStatus.INTERNAL_SERVER_ERROR.value()).message(e.getMessage())
                .path(request.getContextPath()).build();
        }
    }

    @PostMapping("/bidDelete")
    @RequiredAccess(109)
    public ResponseWrapper bidDelete(@RequestParam int bidId) {
        try {
            bidService.bidDelete(bidId);
            return ResponseWrapper.builder().path(request.getServletPath()).data(true).status(HttpStatus.OK.value())
                .build();
        } catch (Exception e) {
            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            return ResponseWrapper.builder().status(HttpStatus.INTERNAL_SERVER_ERROR.value()).message(e.getMessage())
                .path(request.getContextPath()).build();
        }
    }

    @PostMapping("/uploadBidFile")
    @RequiredAccess(103)
    @Transactional
    public ResponseWrapper uploadBidFile(int bidId, int flowId, MultipartFile file) {
        try {
            UserTO userTO = getUserTO();
            bidService.storeFile(bidId, flowId, userTO.getAccountName(), file);
            BidFlowDetails flow = new BidFlowDetails();
            flow.setBidId(bidId);
            flow.setFlowId(flowId);
            flow.setLastUpdateUser(userTO.getAccountName());
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            flow.setLastUpdateTime(sdf.format(new Date()));
            bidFlowService.updateFlow(flow);
            return ResponseWrapper.builder().path(request.getServletPath()).data(true).status(HttpStatus.OK.value())
                .build();
        } catch (Exception e) {
            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            return ResponseWrapper.builder().status(HttpStatus.INTERNAL_SERVER_ERROR.value()).message(e.getMessage())
                .path(request.getContextPath()).build();
        }
    }

    @GetMapping("/getFlows")
    @RequiredAccess(107)
    public ResponseWrapper getFlows(@RequestParam Integer bidId) {
        try {
            Map<Integer, BidFlowDetails> result = bidService.getFlows(bidId);
            return ResponseWrapper.builder().path(request.getServletPath()).data(result).status(HttpStatus.OK.value())
                .build();
        } catch (Exception e) {
            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            return ResponseWrapper.builder().status(HttpStatus.INTERNAL_SERVER_ERROR.value()).message(e.getMessage())
                .path(request.getContextPath()).build();
        }
    }

    @GetMapping("/doDownloadFile")
    @RequiredAccess(104)
    public void doDownloadFile(@RequestParam String fileName, @RequestParam int bidId, @RequestParam int flowId) {
        try {
            byte[] bs = bidService.loadfile(fileName, bidId, flowId);
            String contentType;
            response.reset();
            OutputStream respOut = response.getOutputStream();
            response.addHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.addHeader("Content-Length", String.valueOf(bs.length));
            respOut.write(bs);
            respOut.flush();
            respOut.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @PostMapping("/approveFlow")
    public ResponseWrapper approveFlow(@RequestParam Integer bidId, @RequestParam Integer flowId) {
        try {
            bidFlowService.approved(bidId, flowId, getUserTO().getAccountName());
            return ResponseWrapper.builder().path(request.getServletPath()).data(true).status(HttpStatus.OK.value())
                .build();
        } catch (Exception e) {
            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            return ResponseWrapper.builder().status(HttpStatus.INTERNAL_SERVER_ERROR.value()).message(e.getMessage())
                .path(request.getContextPath()).build();
        }
    }

    @RequestMapping("/deleteBidFile")
    public ResponseWrapper deleteBidFile(@RequestParam Integer bidId, @RequestParam Integer flowId,
        @RequestParam String fileName) {
        try {
            bidService.deleteBidFile(bidId, flowId, fileName, getUserTO().getAccountName());
            return ResponseWrapper.builder().path(request.getServletPath()).data(true).status(HttpStatus.OK.value())
                .build();
        } catch (Exception e) {
            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            return ResponseWrapper.builder().status(HttpStatus.INTERNAL_SERVER_ERROR.value()).message(e.getMessage())
                .path(request.getContextPath()).build();
        }
    }

    @GetMapping("/getBidStatusFileName")
    public ResponseWrapper getBidStatusFileName(@RequestParam Integer bidId) {
        try {
            BidFlowDetails flow = bidService.getFlow(bidId, BidFlowEnum.STATUS.getId());
            return ResponseWrapper.builder().path(request.getServletPath()).data(flow).status(HttpStatus.OK.value())
                .build();
        } catch (Exception e) {
            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            return ResponseWrapper.builder().status(HttpStatus.INTERNAL_SERVER_ERROR.value()).message(e.getMessage())
                .path(request.getContextPath()).build();
        }
    }

    private UserTO getUserTO() throws LoginTimeoutException {
        String encodedToken = request.getHeader("token");
        if (StringUtils.isEmpty(encodedToken)) {
            log.error("token is null.");
            throw new LoginTimeoutException();
        }
        return userService.getUserInfo(encodedToken);
    }

    // 发送响应流方法
    private void setResponseHeader(HttpServletResponse response, String fileName) {
        try {
            try {
                fileName = new String(fileName.getBytes(), "ISO8859-1");
            } catch (UnsupportedEncodingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            response.setContentType("application/octet-stream;charset=ISO8859-1");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.addHeader("Pargam", "no-cache");
            response.addHeader("Cache-Control", "no-cache");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

}
